package com.azt.novel.book.service.impl;


import com.azt.novel.book.dao.entity.BookComment;
import com.azt.novel.book.dao.entity.BookInfo;
import com.azt.novel.book.dao.mapper.BookCommentMapper;
import com.azt.novel.book.dao.mapper.BookInfoMapper;
import com.azt.novel.book.dto.req.BookAddReqDto;
import com.azt.novel.book.dto.req.BookCommentReqDto;
import com.azt.novel.book.dto.resp.BookInfoRespDto;
import com.azt.novel.book.dto.resp.BookRankRespDto;
import com.azt.novel.book.manager.cache.BookInfoCacheManager;
import com.azt.novel.book.manager.cache.BookRankCacheManager;
import com.azt.novel.book.service.IBookInfoService;
import com.azt.novel.common.constant.DatabaseConsts;
import com.azt.novel.common.constant.ErrorCodeEnum;
import com.azt.novel.common.resp.RestResp;
import com.azt.novel.config.annotation.Key;
import com.azt.novel.config.annotation.Lock;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class BookInfoServiceImpl implements IBookInfoService {
    @Resource
    private BookInfoMapper bookInfoMapper;

    @Resource
    private BookInfoCacheManager bookInfoCacheManager;

    @Resource
    private BookRankCacheManager bookRankCacheManager;

    @Resource
    private BookCommentMapper bookCommentMapper;


    @Override
    public RestResp<Void> saveBook(BookAddReqDto dto) {
        // 校验小说名是否已存在
        QueryWrapper<BookInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DatabaseConsts.BookTable.COLUMN_BOOK_NAME, dto.getBookName());
        if (bookInfoMapper.selectCount(queryWrapper) > 0) {
            return RestResp.fail(ErrorCodeEnum.AUTHOR_BOOK_NAME_EXIST);
        }
        BookInfo bookInfo = new BookInfo();
        // 设置作家信息
        bookInfo.setAuthorId(dto.getAuthorId());
        bookInfo.setAuthorName(dto.getPenName());
        // 设置其他信息
        bookInfo.setWorkDirection(dto.getWorkDirection());
        bookInfo.setCategoryId(dto.getCategoryId());
        bookInfo.setCategoryName(dto.getCategoryName());
        bookInfo.setBookName(dto.getBookName());
        bookInfo.setPicUrl(dto.getPicUrl());
        bookInfo.setBookDesc(dto.getBookDesc());
        bookInfo.setIsVip(dto.getIsVip());
        bookInfo.setScore(0);
        bookInfo.setCreateTime(LocalDateTime.now());
        bookInfo.setUpdateTime(LocalDateTime.now());
        // 保存小说信息
        bookInfoMapper.insert(bookInfo);
        return RestResp.ok();
    }

    /**
     * 小说推荐列表查询接口
     * @param bookId
     * @return
     */
    @Override
    public RestResp<List<BookInfoRespDto>> listRecBooks(Long bookId) throws NoSuchAlgorithmException {
        //获取该书的类型
        Long categoryId = bookInfoCacheManager.getBookById(bookId).getCategoryId();
        //根据该类型获取相同类型的500本最新添加的书籍
        List<Long> bookInfoIdList = bookInfoCacheManager.getLastUpdateIdList(categoryId);
        //新建一个推荐书列表
        List<BookInfoRespDto> bookInfoRespDtoList = new ArrayList<>();
        //新建一个Integer列表存储已经存放的书籍的下标
        List<Integer> indexList = new ArrayList<>();
        int count = 0;
        while (count<4){
            //随机从bookInfoIdList中选择一个下标
            int bookIndex = SecureRandom.getInstanceStrong().nextInt(bookInfoIdList.size());
            //该下标的书籍未添加
            if(!indexList.contains(bookIndex)){
                //存放下标
                indexList.add(bookIndex);
//                Long newBookId = bookInfoIdList.get(bookIndex);
                Long newBookId =bookInfoIdList.get(bookIndex);
                BookInfoRespDto book = bookInfoCacheManager.getBookById(newBookId);
                bookInfoRespDtoList.add(book);
                count++;
            }

        }
        return RestResp.ok(bookInfoRespDtoList);
    }

    /**
     * 小说新书榜查询接口
     *
     * @return
     */
    @Override
    public RestResp<List<BookRankRespDto>> listNewestRankBooks() {
        return RestResp.ok(bookRankCacheManager.listNewestRankBooks());
    }

    /**
     * 小说新书榜查询接口
     *
     * @return
     */
    @Override
    public RestResp<List<BookRankRespDto>> listUpdateRankBooks() {
        return RestResp.ok(bookRankCacheManager.listUpdateRankBooks());
    }

    @Override
    public RestResp<List<BookRankRespDto>> listVisitRankBooks() {
        return RestResp.ok(bookRankCacheManager.listVisitRankBooks());
    }

    /**
     * 小说信息查询接口
     * @param bookId
     * @return
     */
    @Override
    public RestResp<BookInfoRespDto> getBookById(Long bookId) {
        return RestResp.ok(bookInfoCacheManager.getBookById(bookId));
    }
    /**
     * 增加小说点击量
     *
     * @param bookId
     * @return
     */
    @Override
    public RestResp<Void> addVisitCount(Long bookId) {
        bookInfoMapper.addVisitCount(bookId);
        return RestResp.ok();
    }

    @Override
    public RestResp<List<BookInfoRespDto>> listBookInfoByIds(List<Long> bookIds) {
        QueryWrapper<BookInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.in(DatabaseConsts.CommonColumnEnum.ID.getName(), bookIds);
        return RestResp.ok(
                bookInfoMapper.selectList(queryWrapper).stream().map(v -> BookInfoRespDto.builder()
                        .id(v.getId())
                        .bookName(v.getBookName())
                        .authorName(v.getAuthorName())
                        .picUrl(v.getPicUrl())
                        .bookDesc(v.getBookDesc())
                        .build()).collect(Collectors.toList()));
    }


    @Lock(prefix = "userComment")
    @Override
    public RestResp<Void> saveComment(
            @Key(expr = "#{userId + '::' + bookId}") BookCommentReqDto dto) {
        // 校验用户是否已发表评论
        QueryWrapper<BookComment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID, dto.getUserId())
                .eq(DatabaseConsts.BookCommentTable.COLUMN_BOOK_ID, dto.getBookId());
        if (bookCommentMapper.selectCount(queryWrapper) > 0) {
            // 用户已发表评论
            return RestResp.fail(ErrorCodeEnum.USER_COMMENTED);
        }
        BookComment bookComment = new BookComment();
        bookComment.setBookId(dto.getBookId());
        bookComment.setUserId(dto.getUserId());
        bookComment.setCommentContent(dto.getCommentContent());
        bookComment.setCreateTime(LocalDateTime.now());
        bookComment.setUpdateTime(LocalDateTime.now());
        bookCommentMapper.insert(bookComment);
        return RestResp.ok();
    }



    @Override
    public RestResp<Void> deleteComment(BookCommentReqDto dto) {
        QueryWrapper<BookComment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DatabaseConsts.CommonColumnEnum.ID.getName(), dto.getCommentId())
                .eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID, dto.getUserId());
        bookCommentMapper.delete(queryWrapper);
        return RestResp.ok();
    }

    @Override
    public RestResp<Void> updateComment(BookCommentReqDto dto) {
        QueryWrapper<BookComment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DatabaseConsts.CommonColumnEnum.ID.getName(), dto.getCommentId())
                .eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID, dto.getUserId());
        BookComment bookComment = new BookComment();
        bookComment.setCommentContent(dto.getCommentContent());
        bookCommentMapper.update(bookComment, queryWrapper);
        return RestResp.ok();
    }

}
